package cn.maihe.elg.operation.centers.fuzhou.channel.service;

import cn.maihe.elg.operation.centers.fuzhou.auth.FZCenterAuthConfig;
import cn.maihe.elg.operation.centers.fuzhou.auth.utils.FZApiCommonUtil;
import cn.maihe.elg.operation.centers.fuzhou.channel.FZBaseChannelService;
import cn.maihe.elg.operation.centers.fuzhou.config.FZMakeInfoConfig;
import cn.maihe.elg.operation.centers.fuzhou.dto.channel.BondDownLoadReqDTO;
import cn.maihe.elg.operation.centers.fuzhou.dto.channel.ChlBizRespData;
import cn.maihe.elg.operation.centers.fuzhou.dto.channel.vo.HyMakeinvoiceObjVO;
import cn.maihe.elg.operation.centers.fuzhou.enums.FZChannelMethod;
import cn.maihe.elg.operation.centers.fuzhou.enums.HyMakeRespCodeEnum;
import cn.maihe.elg.operation.centers.supports.model.bo.PushCenterGuaranteeBo;
import cn.maihe.elg.operation.exception.ErrorCode;
import cn.maihe.elg.operation.exception.SystemRuntimeException;
import cn.maihe.elg.operation.model.dto.InnerBaseResp;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.repository.entity.*;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.guarantee.GuaranteeService;
import cn.maihe.elg.operation.service.invoice.InvoiceInfoService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 出函机构出函后通知 电子保函至平台侧
 * 出函机构（保险公司/银行）在出函后向电子保函平台推送电子保函的下载地址
 * @Author WJH
 * @Date 2021/04/21
 */
@Service
@Slf4j
public class FZBondDownloadChannelService extends FZBaseChannelService<BondDownLoadReqDTO, ChlBizRespData> {

    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private InvoiceInfoService invoiceInfoService;

    @Resource
    private GuaranteeService guaranteeService;

    @Resource
    private BidCustomerService bidCustomerService;

    @Resource
    private InstitutionService institutionService;

    @Autowired
    private ProjectInfoService projectInfoService;

    @Override
    protected FZChannelMethod methodEnum() {
        return FZChannelMethod.bondDownLoad;
    }

    /**
     * 对应接口文档：2.5 电子保函结果推送
     *
     * @param bo
     * @return
     */
    public InnerBaseResp<String> bondDownload(PushCenterGuaranteeBo bo) {
        InnerBaseResp<String> innerBaseResp;

        GuaranteeVo vo = bo.getGuaranteeVo();
        String applyStatus = bo.getApplyStatus();
        String acceptOrderNo = vo.getAcceptOrderNo();

        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(vo.getAcceptOrderNo());
        Assert.notNull(acceptOrderInfo, "查无此受理订单记录");

        CenterNoEnum centerNoEnum = this.getCenterNoEnumById(acceptOrderInfo.getCenterId());

        GuaranteeDO guarantee = guaranteeService.getGuaranteeByAcceptOrderNo(acceptOrderNo);

        GuaranteeInstitutionDO institutionDO = institutionService.getInstitutionByAcceptOrderNo(acceptOrderNo);
        ProjectInfoDO projectInfoDO = projectInfoService.selectById(acceptOrderInfo.getProjectId());

        FZCenterAuthConfig authConfig = fzMakeInfoConfig.getAuthConfig(CenterNoEnum.FUZHOU);
        FZMakeInfoConfig.CenterInfo centerInfo = authConfig.getCenterInfo();

        BondDownLoadReqDTO reqDTO = new BondDownLoadReqDTO();
        reqDTO.setMethod("insurer_push_guarantee");
        reqDTO.setTimestamp(cn.hutool.core.date.DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        reqDTO.setBtcId(centerInfo.getBtcId());
        reqDTO.setEnterInstitutionType("4");
        reqDTO.setOrderNo(acceptOrderInfo.getCenterOrderId());
        reqDTO.setGuaranteeNo(acceptOrderInfo.getGuaranteeNo());
        reqDTO.setPrincipal(acceptOrderInfo.getBidCustomerName());
        reqDTO.setCreditor(projectInfoDO.getTenderer());
        reqDTO.setGuarantor(institutionDO.getGuarantorName());
        reqDTO.setOutGuaranteeTime(DateUtil.getStringFromDate(acceptOrderInfo.getGuaranteeTime(), "yyyy-MM-dd HH:mm:ss"));
        reqDTO.setGuaranteePdfHash("");
        reqDTO.setTransNo(IdGenerate.getIdStr(20));


        // 获取保函文件(本地)
        GuaranteeAttachmentInfoDO typeAttachmentByAcceptOrderNo = guaranteeAttachmentInfoService.getTypeAttachmentByAcceptOrderNo(acceptOrderNo, AttachmentFileType.TYPE_0);
        Path filePath = elgResourceService.getAbsolutePath(typeAttachmentByAcceptOrderNo.getFilePath());
        reqDTO.setGuaranteePdfHash(FZApiCommonUtil.calculateHash(filePath.toString(), "SHA-256"));

        // 请求参数
        Map<String, Object> requestParam = new HashMap<>();
        // 4. 构建 MultiValueMap，用于封装文件和其他表单参数
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();

        try {
            body.add("access_token", FZApiCommonUtil.getAccessToken());
//            body.add("param","");
            // 先通过File对象检查路径
            ElgLogger.error(log, l -> l.info("acceptOrderNo={} => 附件id[{}][{}] filePath:{}", acceptOrderNo, typeAttachmentByAcceptOrderNo.getId(), typeAttachmentByAcceptOrderNo.getFilePath(), filePath));
            File file = new File(filePath.toString());
            if (!file.exists()) {
                throw new SystemRuntimeException(ErrorCode.NOTEXISTS, "文件路径不存在: " + file.getAbsolutePath());
            }
            if (!file.isFile()) {
                throw new SystemRuntimeException(ErrorCode.NOT_FILE, "路径不是文件: " + file.getAbsolutePath());
            }
            if (!file.canRead()) {
                throw new SystemRuntimeException(ErrorCode.NOT_READ, "无法读取文件: " + file.getAbsolutePath());
            }
            // ---------- 新增：文件大小检查 ----------
            long fileSize = Files.size(filePath); // 获取文件大小（字节）

            // 1. 检查文件是否为空（0字节）
            if (fileSize == 0) {
                throw new SystemRuntimeException(ErrorCode.INVALID_SIZE, "文件内容为空: " + filePath);
            }

            // 使用FileSystemResource
            FileSystemResource fileResource = new FileSystemResource(file);
            body.add("guarantee_pdf", fileResource); // 确保参数名正确
//            FileSystemResource fileResource = new FileSystemResource(filePath);
//            if (fileResource.exists()) {
//                body.add("guarantee_pdf", fileResource); // "file" 是表单中文件参数的名称
//            } else {
//                throw new SystemRuntimeException(ErrorCode.NOTEXISTS, filePath + "保函文件资源不存在");
//            }

//            byte[] bFile = Files.readAllBytes(filePath);
//            requestParam.put("access_token", FZApiCommonUtil.getAccessToken());
//            requestParam.put("param", "");
//            requestParam.put("guarantee_pdf", String.valueOf(bFile));

        } catch (Exception e) {
            log.error("开函结果通知,获取保函文件失败： >> [{}] 异常:{}", centerNoEnum.getCenterName(), e.getMessage(), e);
        }

//        reqDTO.setInsuranceNo(acceptOrderInfo.getAcceptOrderNo());
//        reqDTO.setPolicyNo(acceptOrderInfo.getGuaranteeNo());
//        String policyUrl = guaranteeAttachmentInfoService.buildAttachDownloadUrl(acceptOrderNo, AttachmentFileType.TYPE_7);
//        reqDTO.setGuaranteeUrl(policyUrl);
//        // 申请书+协议书 合同
//        reqDTO.setPolicyUrl(policyUrl);
//        reqDTO.setGuaranteeOutTime(DateUtil.formateDate(vo.getGuaranteeTime(), "yyyy-MM-dd HH:mm:ss"));
//        reqDTO.setInsurStartDate(DateUtil.formateDate(vo.getServiceBeginTime(), "yyyy-MM-dd"));
//        reqDTO.setInsurEndDate(DateUtil.formateDate(vo.getServiceEndTime(), "yyyy-MM-dd"));
//        /**
//         * 担保责任：一般保证、连带责任保证、独立保函
//         */
//        reqDTO.setGuaranteeDuty("独立保函");
//        /**从属性：独立保函、从合同*/
//        reqDTO.setGuaranteeProperty("独立保函");
//        reqDTO.setClaimClause(this.getClaimClause());
//        reqDTO.setPayLimitation("7日内");
//        reqDTO.setBankRecordNo("无");
//        reqDTO.setApplicableLaw("担保法、保险法、《独立保函司法解释》（法释〔2016〕24 号）");
//        reqDTO.setRemark("担保公司保函");
//        reqDTO.setReceiptUrl(guaranteeAttachmentInfoService.buildAttachDownloadUrl(acceptOrderNo, AttachmentFileType.TYPE_6));
//        reqDTO.setGuaranteeOfdUrl(guaranteeAttachmentInfoService.buildAttachDownloadUrl(acceptOrderNo, AttachmentFileType.TYPE_0));
//        reqDTO.setGuaranteeOfdMD5(guaranteeAttachmentInfoService.getTypeAttachmentByAcceptOrderNo(acceptOrderNo, AttachmentFileType.TYPE_0).getFileMd5());
//        reqDTO.setGuaranteeXmlUrl(guaranteeAttachmentInfoService.buildAttachDownloadUrl(acceptOrderNo, AttachmentFileType.TYPE_14));
//        reqDTO.setGuaranteeXMlMD5(guaranteeAttachmentInfoService.getTypeAttachmentByAcceptOrderNo(acceptOrderNo, AttachmentFileType.TYPE_14).getFileMd5());
//        reqDTO.setInvoiceObj(this.buildInvoiceObj(acceptOrderInfo));


        try {
            ChlBizRespData bizRespData = this.doRequest(centerNoEnum, reqDTO, body);
            if (HyMakeRespCodeEnum.isSuccess(bizRespData.getCode())) {
                bo.getGuaranteeVo().setSerialNum(bizRespData.getMessage());
                //重试机制需要在此处更新中心返回的序列号
                guarantee.setSerialNum(bizRespData.getMessage());
                guaranteeService.updateById(guarantee);
                innerBaseResp = InnerBaseResp.success(bo);
            } else {
                innerBaseResp = InnerBaseResp.error(bo, bizRespData.getMessage());
            }
        } catch (Exception e) {
            log.error("开函结果通知 >> [{}] 异常:{}", centerNoEnum.getCenterName(), e.getMessage(), e);
            innerBaseResp = InnerBaseResp.error("通知异常:" + e.getMessage());
        }

        return innerBaseResp;
    }

    private HyMakeinvoiceObjVO buildInvoiceObj(AcceptOrderInfoDO acceptOrderInfo) {
        InvoiceInfoDO info = invoiceInfoService.selectById(acceptOrderInfo.getInvoiceId());

        HyMakeinvoiceObjVO objVO = new HyMakeinvoiceObjVO();
        objVO.setInvoiceUrl(info.getPdfUrl());
        objVO.setInvoiceCode(info.getInvoiceCode());
        objVO.setInvoiceNo(info.getInvoiceNo());
        objVO.setApplyStatus(StringUtil.isNotBlank(info.getInvoiceNo()) ? "1" : "0");
        objVO.setOpenTime(DateUtil.formateDate(info.getGmtCreate(), "yyyy-MM-dd HH:mm:ss"));
        objVO.setInvoiceTitle(info.getInvoiceTitle());
        objVO.setCustomerAddress(info.getCustomerAddress());
        objVO.setCustomerPhone(info.getCustomerPhone());
        objVO.setProductName("*金融服务*保函费");
        objVO.setAmount(StringUtil.toYuan(info.getAmount()));
        objVO.setAmountOfChinaese(info.getAmountOfChinaese());
        objVO.setSellerName(info.getSellerName());
        objVO.setSellerCreditCode(info.getSellerCreditCode());
        objVO.setSellerBankCode(info.getSellerBankCode());
        objVO.setSellerOpenBank(info.getSellerOpenBank());
        objVO.setSellerAddress(info.getSellerAddress());
        objVO.setSellerPhone(info.getSellerPhone());
        objVO.setHandler(info.getHandler());
        objVO.setInvoiceRemark(info.getInvoiceRemark());
        return objVO;
    }


    /**
     * 索赔条款
     *
     * @return
     */
    public String getClaimClause() {
        return "1、投标人在投标有效期内撤销或修改其投标文件的；\n" +
                "2、投标人中标后，非因不可抗力原因放弃中标、无正当理由不与招标人订立合同、在签订合同时向招标人提出附加条件、或者不按照招标文件要求提交履约担保金的；\n" +
                "3、投标人的投标文件存在投标须知第20.6款规定的雷同情形之一；\n" +
                "4、投标人中标后，因违法行为导致中标被依法确认无效的；\n" +
                "5、法律、法规规定的其他没收投标保证金情形。\n" +
                "本保函在投标有效期到期后28日（含）内或招标人延长投标有效期后的到期日后28日（含）内保持有效，延长投标有效期无须通知我方，但任何索款要求应在投标有效期内送达我方。保函失效后请将本保函交投标人退回我方注销。\n" +
                "本保函项下所有权利和义务均受中华人民共和国法律管辖和制约。";
    }

}
